package com.gameloft.input;

import javax.microedition.lcdui.Canvas;


public class Keypad
{
  
  //Key flags
  public final static int FLAG_KEY_0 = 0x00000001;
  public final static int FLAG_KEY_1 = 0x00000002;
  public final static int FLAG_KEY_2 = 0x00000004;
  public final static int FLAG_KEY_3 = 0x00000008;
  public final static int FLAG_KEY_4 = 0x00000010;
  public final static int FLAG_KEY_5 = 0x00000020;
  public final static int FLAG_KEY_6 = 0x00000040;
  public final static int FLAG_KEY_7 = 0x00000080;
  public final static int FLAG_KEY_8 = 0x00000100;
  public final static int FLAG_KEY_9 = 0x00000200;
  public final static int FLAG_KEY_UP = 0x00000400;
  public final static int FLAG_KEY_DOWN = 0x00000800;
  public final static int FLAG_KEY_LEFT = 0x00001000;
  public final static int FLAG_KEY_RIGHT = 0x00002000;
  public final static int FLAG_KEY_POUND = 0x00004000;
  public final static int FLAG_KEY_STAR = 0x00008000;
  public final static int FLAG_KEY_SELECT = 0x00010000;
  public final static int FLAG_KEY_OK = 0x00020000;
  public final static int FLAG_KEY_BACK = 0x00040000;
  
	//Key combo flags
	public final static int FLAG_KEYS_UP = FLAG_KEY_UP | FLAG_KEY_2;
	public final static int FLAG_KEYS_DOWN = FLAG_KEY_DOWN | FLAG_KEY_8;
	public final static int FLAG_KEYS_LEFT = FLAG_KEY_LEFT | FLAG_KEY_4;
	public final static int FLAG_KEYS_RIGHT = FLAG_KEY_RIGHT | FLAG_KEY_6;
	public final static int FLAG_KEYS_SELECT = FLAG_KEY_OK | FLAG_KEY_SELECT | FLAG_KEY_5;
	public final static int FLAG_KEYS_BACK = FLAG_KEY_BACK | FLAG_KEY_0;
	
  //Key status
  private static int keysHeld = 0;
  private static int keysPressed = 0;
  private static int keysReleased = 0;
  private static int keysDown = 0;
  private static int keysUp = 0;
  
  //Custom keycodes array position constants
  private final static int UP = 0;
  private final static int DOWN = 1;
  private final static int LEFT = 2;
  private final static int RIGHT = 3;
  private final static int SELECT = 4;
  private final static int OK = 5;
  private final static int BACK = 6;
  
	//Default custom and standar keycodes
  private final static int[] defaultCustomKeycodes = { -1, -2, -3, -4, -5, -6, -7 };
  private final static int[] standarKeycodes = { Canvas.KEY_NUM0, Canvas.KEY_NUM1, Canvas.KEY_NUM2,
																								 Canvas.KEY_NUM3, Canvas.KEY_NUM4, Canvas.KEY_NUM5,
																								 Canvas.KEY_NUM6, Canvas.KEY_NUM7, Canvas.KEY_NUM8,
																								 Canvas.KEY_NUM9, Canvas.KEY_POUND, Canvas.KEY_STAR };
	
	//Custom keycodes array
	private static int[] customKeycodes = defaultCustomKeycodes;
	
	
	//Returns true if at least one of the keys represented by the supplied flags were pressed in last frame
	public static boolean wasPressed(int keyFlags)
	{
		return (keysPressed & keyFlags) != 0;
	}
	
	//Returns true if at least one of the keys represented by the supplied flags were released in last frame
	public static boolean wasReleased(int keyFlags)
	{
		return (keysReleased & keyFlags) != 0;
	}
	
	//Returns true if at least one of the keys represented by the supplied flags are currently being held
	public static boolean isHeld(int keyFlags)
	{
		return (keysHeld & keyFlags) != 0;
	}
	
  //Validate and set the custom keycodes. Throws IllegalArgumentException if this array contains an invalid
  //set of keycodes (overlaps with std keycodes and/or itself) or the array's lenght is different than 7.
  public static void setCustomKeycodes(int[] newKeycodes) throws IllegalArgumentException
  {
  	if (newKeycodes.length < 7) throw new IllegalArgumentException("Array lenght != 7");
  	
  	for (int i = 0; i < newKeycodes.length; i++)
		{
			if (newKeycodes[i] == 0)
				throw new IllegalArgumentException("Invalid keycode 0 at index "+i);
			
			for (int j = 0; j < standarKeycodes.length; j++)
			{
				if (newKeycodes[i] == standarKeycodes[j])
					throw new IllegalArgumentException("Standar keycode found at index "+i);
			}
			for (int j = i + 1; j < newKeycodes.length; j++)
			{
				if (newKeycodes[i] == newKeycodes[j])
					throw new IllegalArgumentException("Duplicated keycode at indexes "+i+", "+j);
			}
  	}
		
		for (int i = 0; i < newKeycodes.length; i++)
			System.out.println("newKeycodes["+i+"] "+newKeycodes[i]);
		
  	customKeycodes = newKeycodes;
  }
  
  //Discards any custom keycode mapping and sets default values
  public static void setDefaultCustomKeycodes()
  {
  	customKeycodes = defaultCustomKeycodes;
  }
  
  //Should be called everytime a keyPressed event is triggered in the app's canvas.
  public static void keyPressed(int keyCode)
  {
  	int keyMask = getKeyMask(keyCode);
		keysHeld |= keyMask;
		keysDown |= keyMask;
  }
  
  //Should be called everytime a keyReleased event is triggered in the app's canvas.
  public static void keyReleased(int keyCode)
  {
    int keyMask = getKeyMask(keyCode);
		keysHeld &= ~keyMask;
		keysUp |= keyMask;
  }
  
  //Should be called once per frame before the app's logic update.
  public static void update()
  {
  	keysPressed = keysDown;
  	keysReleased = keysUp;
  	keysDown = 0;
  	keysUp = 0;
  }
  
  //Called internally to obtain a key flag for the desired keyCode
  private static int getKeyMask(int keyCode)
  {
  	if (keyCode == Canvas.KEY_NUM0) return FLAG_KEY_0;
    if (keyCode == Canvas.KEY_NUM1) return FLAG_KEY_1;
    if (keyCode == Canvas.KEY_NUM2) return FLAG_KEY_2;
    if (keyCode == Canvas.KEY_NUM3) return FLAG_KEY_3;
    if (keyCode == Canvas.KEY_NUM4) return FLAG_KEY_4;
    if (keyCode == Canvas.KEY_NUM5) return FLAG_KEY_5;
    if (keyCode == Canvas.KEY_NUM6) return FLAG_KEY_6;
    if (keyCode == Canvas.KEY_NUM7) return FLAG_KEY_7;
    if (keyCode == Canvas.KEY_NUM8) return FLAG_KEY_8;
    if (keyCode == Canvas.KEY_NUM9) return FLAG_KEY_9;
    if (keyCode == Canvas.KEY_POUND) return FLAG_KEY_POUND;
    if (keyCode == Canvas.KEY_STAR) return FLAG_KEY_STAR;
    
    if (keyCode == customKeycodes[UP]) return FLAG_KEY_UP;
    if (keyCode == customKeycodes[DOWN]) return FLAG_KEY_DOWN;
    if (keyCode == customKeycodes[LEFT]) return FLAG_KEY_LEFT;
    if (keyCode == customKeycodes[RIGHT]) return FLAG_KEY_RIGHT;
    if (keyCode == customKeycodes[SELECT]) return FLAG_KEY_SELECT;
    if (keyCode == customKeycodes[OK]) return FLAG_KEY_OK;
    if (keyCode == customKeycodes[BACK]) return FLAG_KEY_BACK;
    
    return 0;
  }
  
}